﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using CodeStash.Utils;
using System.Web;
using CodeStash.Models.Snippet;
using System.Text;
using System.Web.Security;

namespace CodeStash.ExtensionsMethods
{
    public static class HtmlHelperExtensions
    {
        public static MvcHtmlString ComboFor<TModel, TItem, TValue, TKey>(
            this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TValue>> selectedItemExpr,
            Expression<Func<TModel, IEnumerable<TItem>>> enumerableExpr,
            Expression<Func<TItem, TValue>> valueExpr,
            Expression<Func<TItem, TKey>> keyExpr,
            IDictionary<string, object> htmlAttributes) where TValue : IComparable
        {
            TModel model = (TModel)htmlHelper.ViewData.Model;

            string id = ExpressionUtils.GetPropertyName(selectedItemExpr);

            TValue selectedItem = selectedItemExpr.Compile()(model);
            IEnumerable<TItem> sourceItems = enumerableExpr.Compile()(model);

            Func<TItem, TKey> keyFunc = keyExpr.Compile();
            Func<TItem, TValue> valueFunc = valueExpr.Compile();



            List<SelectListItem> selectList =
                (from item in sourceItems
                 let itemValue = valueFunc(item)
                 let itemKey = keyFunc(item)
                 select new SelectListItem()
                     {
                         Selected = selectedItem.CompareTo(itemValue) == 0,
                         Text = itemKey.ToString(),
                         Value = itemValue.ToString()
                     }).ToList();

            return htmlHelper.DropDownList(id.ToString(), selectList, htmlAttributes);

        }



        public static MvcHtmlString ScriptTag(this HtmlHelper html, string path)
        {
            //Build up a string like this one
            //<script src="@Url.Content("~/Scripts/jquery-1.6.4.min.js")" type="text/javascript"></script>
            HttpContextBase context = html.ViewContext.RequestContext.HttpContext;
            UrlHelper url = new UrlHelper(html.ViewContext.RequestContext);

            if (System.IO.File.Exists(context.Request.MapPath(path)))
            {
                path = AppendHash(html, path);

                TagBuilder script = new TagBuilder("script");
                script.MergeAttribute("src", url.Content(path));
                script.MergeAttribute("type", "text/javascript");
                return MvcHtmlString.Create(script + "\r\n");
            }

            return MvcHtmlString.Empty;
        }



        public static MvcHtmlString CssTag(this HtmlHelper html, string path)
        {
            //Build up a string like this one
            //   <link href="@Url.Content("~/Content/site.css")" rel="stylesheet" type="text/css" />
            HttpContextBase context = html.ViewContext.RequestContext.HttpContext;
            UrlHelper url = new UrlHelper(html.ViewContext.RequestContext);

            if (System.IO.File.Exists(context.Request.MapPath(path)))
            {
                path = AppendHash(html, path);

                TagBuilder script = new TagBuilder("link");
                script.MergeAttribute("href", url.Content(path));
                script.MergeAttribute("rel", "stylesheet");
                script.MergeAttribute("type", "text/css");
                return MvcHtmlString.Create(script + "\r\n");
            }

            return MvcHtmlString.Empty;
        }


        public static string AppendHash(this HtmlHelper html, string path)
        {
            if (html.ViewContext.HttpContext.Cache.Get("__ContentWatcher") != null)
            {
                ContentWatcher contentWatcher = html.ViewContext.HttpContext.Cache["__ContentWatcher"] as ContentWatcher;
                if (contentWatcher != null && contentWatcher.ContainsKey(path))
                {
                    return string.Format("{0}?v={1}", path, contentWatcher[path]);
                }
            }

            return path;
        }


        public static MvcHtmlString Ratings(this HtmlHelper helper, SnippetRatingModel snippet)
        {
            StringBuilder sb = new StringBuilder();
            var user = Membership.GetUser();

            if (user != null)
            {
                sb.AppendFormat("<span class='rating' rating='{0}' codeSnippetId='{1}' title='Click to cast vote'>", snippet.Rating, snippet.CodeSnippetId);
                string formatStr = "<img src='/Content/Images/{0}' alt='star' width='12' height='12' class='star' value='{1}' />";

                int currentRating = snippet.Rating;
                if (currentRating == 0)
                {
                    for (int i = 1; i <= 5; i++)
                    {
                        sb.AppendFormat(formatStr, "star-off.png", i);
                    }
                }
                else
                {
                    for (Double i = 1; i <= 5; i++)
                    {
                        if (i <= snippet.Rating)
                        {
                            sb.AppendFormat(formatStr, "star-on.png", i);
                        }
                        else
                        {
                            sb.AppendFormat(formatStr, "star-off.png", i);
                        }
                    }
                }
            }

            if (snippet.TotalRaters > 0)
            {
                // Don't show this where we have no ratings.
                sb.AppendFormat("&nbsp;<span>Currently rated {0:0.##} by {1} user(s)</span>", snippet.AverageRating, snippet.TotalRaters);
            }
            else
            {
                if (user != null)
                {
                    sb.Append("&nbsp;<span>This snippet currently has no votes. Why not be the first to rate it?</span>");
                }
                else
                {
                    sb.Append("&nbsp;<span>This snippet currently has no votes. Why not log in and be the first to rate it?</span>");
                }
            }

            sb.Append("</span>");
            return new MvcHtmlString(sb.ToString());
        }



    }

}